package com.izhengyin.gateway.base;

import com.alibaba.fastjson.JSON;
import com.izhengyin.gateway.base.constant.Attribute;
import com.izhengyin.gateway.base.pojo.Api;
import com.izhengyin.gateway.base.pojo.Metrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

/**
 * @author zhengyin zhengyinit@outlook.com
 * Created on 2020-12-22 16:07
 */
@Service
public class MetricsService {
    private final StatisticsService statisticsService;
    private static Logger metricsLog = LoggerFactory.getLogger("gatewayMetricsLog");
    public MetricsService(
            StatisticsService statisticsService
    ){
        this.statisticsService = statisticsService;
    }

    /**
     * 创建并记录指标
     * @param swe
     */
    public void createMetricsAndRecord(ServerWebExchange swe){
        createMetricsAndRecord(swe,null);
    }

    /**
     * 创建并记录指标
     * @param swe
     * @param throwable
     */
    public void createMetricsAndRecord(ServerWebExchange swe , Throwable throwable){
        Api api = swe.getAttribute(Attribute.API);
        if(Objects.isNull(api)){
            return;
        }
        String clientIp = Optional.ofNullable(swe.getAttribute(Attribute.CLIENT_IP)).map(String::valueOf).orElse("");
        long requestTimeMs = (long) Optional.ofNullable(swe.getAttribute(Attribute.REQUEST_TIME_MS)).orElse(0L);
        String gateway = Optional.ofNullable(swe.getAttribute(Attribute.GATEWAY)).map(String::valueOf).orElse("");
        String traceId = Optional.ofNullable(swe.getAttribute(Attribute.TRACE_ID)).map(String::valueOf).orElse("");
        String spanId = Optional.ofNullable(swe.getAttribute(Attribute.SPAN_ID)).map(String::valueOf).orElse("");
        Boolean sampled = swe.getAttribute(Attribute.SAMPLED);
        ServerHttpRequest request = swe.getRequest();
        final Metrics metrics = new Metrics();
        metrics.setGateway(gateway);
        metrics.setService(api.getServer());
        metrics.setName(Optional.ofNullable(api.getName()).filter(v -> !StringUtils.isEmpty(v)).orElse("nil"));
        metrics.setMapping(api.getMappingInfo());
        metrics.setJMethod(api.getMethod());
        metrics.setHttpMethod(request.getMethodValue());
        metrics.setHttpCode(Optional.ofNullable(swe.getResponse().getStatusCode()).map(HttpStatus::value).orElse(0));
        metrics.setUri(request.getURI().getPath());
        metrics.setUserAgent(request.getHeaders().getFirst("User-Agent"));
        metrics.setClientIp(clientIp);
        metrics.setTimestamp(new Date(requestTimeMs));
        metrics.setErrorType(Optional.ofNullable(throwable).map(err -> err.getClass().getName()).orElse("nil"));
        metrics.setErrorMessage(Optional.ofNullable(throwable).map(Throwable::getMessage).orElse("nil"));
        metrics.setResTimeMs(System.currentTimeMillis() - metrics.getTimestamp().getTime());
        metrics.setTraceId(traceId);
        metrics.setSpanId(spanId);
        metrics.setSampled(sampled);
        //记录 metrics
        metricsLog.info(metrics.toDelimiterString());
        //网关内部统计
        this.statisticsService.collect(metrics);
    }
}
